/*
 * Copyright Hundsun Technologies Inc. All Rights Reserved.
 */

package memdb

import (
	"github.com/syndtr/goleveldb/leveldb/comparer"
	"github.com/syndtr/goleveldb/leveldb/errors"
	"github.com/syndtr/goleveldb/leveldb/memdb"
	"github.com/syndtr/goleveldb/leveldb/util"
	"hundsun.com/hsl/hschain/common/config"
	"hundsun.com/hsl/hschain/common/types"
	dbm "hundsun.com/hsl/hschain/store/db"
)

func init() {
	dbm.Register("memdb", NewMemdb)
}

//Memdb db
type Memdb struct {
	db *memdb.DB
}

//NewMemdb new memdb
func NewMemdb(cfg *config.PluginConfig) (dbm.Database, error) {
	return &Memdb{
		db: memdb.New(comparer.DefaultComparer, 0),
	}, nil
}

//Get get
func (db *Memdb) Get(key []byte) ([]byte, error) {
	v, err := db.db.Get(key)
	if err != nil {
		if err == errors.ErrNotFound {
			return nil, types.ErrNotFound
		}
		return nil, err
	}
	return cloneByte(v), nil
}

// Gets 批量获取
func (db *Memdb) Gets(keys [][]byte) ([][]byte, error) {
	values := make([][]byte, len(keys))
	for i, key := range keys {
		v, err := db.db.Get(key)
		if err == nil {
			values[i] = cloneByte(v)
		}
	}
	return values, nil
}

//Set set
func (db *Memdb) Set(key []byte, value []byte) error {
	err := db.db.Put(key, value)
	if err != nil {
		return err
	}
	return nil
}

//Has has
func (db *Memdb) Has(key []byte) (bool, error) {
	return db.db.Contains(key), nil
}

//Delete 删除
func (db *Memdb) Delete(key []byte) error {
	err := db.db.Delete(key)
	if err != nil {
		return err
	}
	return nil
}

//DB db
func (db *Memdb) DB() *memdb.DB {
	return db.db
}

//Close 关闭
func (db *Memdb) Close() {
}

//NewBatch new
func (db *Memdb) NewBatch(sync bool) dbm.Batch {
	return &memBatch{db: db}
}

// NewIteratorWithRange new range iterator
func (db *Memdb) NewIteratorWithRange(start []byte, limit []byte) dbm.Iterator {
	return db.db.NewIterator(&util.Range{Start: start, Limit: limit})
}

// NewIteratorWithPrefix new prefix iterator
func (db *Memdb) NewIteratorWithPrefix(prefix []byte) dbm.Iterator {
	return db.db.NewIterator(util.BytesPrefix(prefix))
}

// List ...
type List struct {
	*Memdb
}

// NewList new list
func (db *Memdb) NewList() dbm.Lister {
	return &List{db}
}

// ListRange count < 0 则对取值数量不做限制
func (db *List) ListRange(start, limit []byte, count int32, opt dbm.Option) ([][]byte, [][]byte, error) {
	it := db.NewIteratorWithRange(start, limit)
	defer it.Release()
	return dbm.List(it, count, opt)
}

// ListPrefix count < 0 则对取值数量不做限制
func (db *List) ListPrefix(prefix []byte, count int32, opt dbm.Option) ([][]byte, [][]byte, error) {
	it := db.NewIteratorWithPrefix(prefix)
	defer it.Release()
	return dbm.List(it, count, opt)
}

// RangeCount 查询Range范围内迭代个数
func (db *List) RangeCount(start, limit []byte) int64 {
	it := db.NewIteratorWithRange(start, limit)
	defer it.Release()
	return dbm.ListCount(it)
}

// PrefixCount 查询prefix迭代个数
func (db *List) PrefixCount(prefix []byte) int64 {
	it := db.NewIteratorWithPrefix(prefix)
	defer it.Release()
	return dbm.ListCount(it)
}

type kv struct{ k, v []byte }
type memBatch struct {
	db     *Memdb
	writes []kv
	size   int
	len    int
}

// ValueSize 值大小
func (b *memBatch) ValueSize() int {
	return b.size
}

// Set batch set
func (b *memBatch) Set(key, value []byte) error {
	b.writes = append(b.writes, kv{cloneByte(key), cloneByte(value)})
	b.size += len(value)
	b.size += len(key)
	b.len += len(value)
	return nil
}

// Delete batch delete
func (b *memBatch) Delete(key []byte) error {
	b.writes = append(b.writes, kv{cloneByte(key), nil})
	b.size += len(key)
	b.len++
	return nil
}

// Write batch write
func (b *memBatch) Write() error {
	var err error
	for _, kv := range b.writes {
		if kv.v == nil {
			err = b.db.Delete(kv.k)
		} else {
			err = b.db.Set(kv.k, kv.v)
		}
	}
	return err
}

//ValueLen  batch数量
func (b *memBatch) ValueLen() int {
	return b.len
}

// Reset batch reset
func (b *memBatch) Reset() {
	//重置batch自己的buf，不能调用db reset，将直接清空db历史数据
	b.writes = b.writes[:0]
	b.size = 0
	b.len = 0
}

func cloneByte(v []byte) []byte {
	value := make([]byte, len(v))
	copy(value, v)
	return value
}
